import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { Path, Text, Range, Node } from 'slate';
import { css } from 'emotion';
import { isHotkey } from 'is-hotkey';

import { SearchContext, icons } from '../share';
import { Portal } from '../component';

export const Search = () => {
  const { setSearch } = useContext(SearchContext);
  const [show, setShow] = useState(false);
  const inputRef = useRef<HTMLInputElement | null>(null);
  const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {
    if (isHotkey('enter', e.nativeEvent)) {
      setSearch(inputRef.current!.value || '');
    }
  }, []);

  useEffect(() => {
    window.onkeydown = function (e) {
      if (isHotkey('cmd+f', e)) {
        e.stopPropagation();
        e.preventDefault();
        setShow(true);
      }
    };
    return () => {
      window.onkeydown = null;
    };
  }, []);

  return (
    <Portal>
      <div
        className={css`
          position: fixed;
          top: 100px;
          right: 100px;
          background-color: white;

          padding: 5px;
          box-shadow: 0px 0px 1px 1px #cecece;

          display: inline-flex;

          opacity: ${show ? 1 : 0};
        `}
      >
        <input
          ref={inputRef}
          className={css`
            border: none;
            :focus-visible {
              outline: none;
            }
          `}
          onKeyDown={onKeyDown}
        />
        <span
          className={css`
            width: 16px;
            margin-left: 4px;
            display: inline-flex;
          `}
          onClick={() => {
            setShow(false);
            inputRef.current!.value = '';
            setSearch('');
          }}
        >
          {icons['close']()}
        </span>
      </div>
    </Portal>
  );
};

export const searchDecorate = ([node, path]: [Node, Path]) => {
  // FIXME: #1 React has detected a change in the order of Hooks called by Editable.
  const { search } = useContext(SearchContext);

  const ranges: Range[] = [];
  if (search && Text.isText(node)) {
    const { text } = node;
    const parts = text.split(search);
    let offset = 0;

    parts.forEach((part, i) => {
      if (i !== 0) {
        ranges.push({
          anchor: { path, offset: offset - search.length },
          focus: { path, offset },
          highlight: true,
        });
      }

      offset = offset + part.length + search.length;
    });
  }

  return ranges;
};
